﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Expertime.Multitude.Intranet.Utils;

namespace Expertime.Multitude.Intranet.Security
{
    public static class GroupManager
    {
        /// <summary>
        /// Create a group
        /// </summary>
        /// <param name="currentSite"></param>
        /// <param name="groupname"></param>
        /// <param name="owner"></param>
        /// <param name="groupDescription"></param>
        /// <param name="permissionLevel"></param>
        public static void CreateGroup(SPWeb currentSite, string groupname, string permissionLevel, string owner, string groupDescription)
        {
            try
            {
                // only create the group if it does not exist
                if (!ContainsGroup(currentSite.SiteGroups, groupname))
                {
                    // Set the owner and add if not exists to the web site users
                    SPUser ownerUser = currentSite.EnsureUser(owner);

                    // add the group
                    currentSite.SiteGroups.Add(groupname, ownerUser, ownerUser, groupDescription);

                    // security
                    SetRoleDefinitionBinding(currentSite, groupname, permissionLevel);

                   LogManager.LogDebug("[GroupManager.CreateGroup] Création du groupe", string.Format("[groupname={0}, permissionLevel={1}]", groupname, permissionLevel));
                }
                else
                    LogManager.LogDebug("[GroupManager.CreateGroup] Groupe déjà existant", string.Format("[groupname={0}, permissionLevel={1}]", groupname, permissionLevel));
            }
            catch (Exception ex) { LogManager.LogException(ex, string.Format("[GroupManager.CreateGroup][groupname={0}, permissionLevel={1}] Erreur lors de la création du groupe", groupname, permissionLevel)); }
        }

        /// <summary>
        /// Group exists
        /// </summary>
        /// <param name="groupCollection"></param>
        /// <param name="groupname"></param>
        /// <returns></returns>
        public static bool ContainsGroup(SPGroupCollection groupCollection, string groupname)
        {
            try
            {
                SPGroup group = groupCollection[groupname];
                return (group!=null);
            }
            catch (SPException ex)
            {
                LogManager.LogException(ex, string.Format("[GroupManager.ContainsGroup]Erreur lors de la recherche du groupe '{0}'", groupname));
                return false;
            }
        }

        /// <summary>
        /// add the user to the sharepoint group
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="currentSite"></param>
        /// <param name="username"></param>
        public static void AddUsersToGroup(SPWeb currentSite, string groupName, string username)
        {
            SPGroup group = currentSite.SiteGroups[groupName];
            if (group!=null)
                group.AddUser(username, string.Empty, username, string.Empty);
        }

        /// <summary>
        /// add the read role definition to the site group
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="currentSite"></param>
        /// <param name="permissionLevel"></param>
        public static void SetRoleDefinitionBinding(SPWeb currentSite, string groupName, string permissionLevel)
        {
            SPGroup group = currentSite.SiteGroups[groupName];
            SPRoleDefinition roleDefinition = currentSite.RoleDefinitions[permissionLevel];

            SPRoleAssignment roleAssignment = new SPRoleAssignment(group);
            roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
            currentSite.RoleAssignments.Add(roleAssignment);
            currentSite.Update();
        }

        /// <summary>
        /// Récupère un groupe existant
        /// </summary>
        /// <param name="groups"></param>
        /// <param name="groupName"></param>
        public static SPGroup GetGroup(SPGroupCollection groups, string groupName)
        {
            SPGroup group = null;
            try { group = groups[groupName]; }
            catch (Exception ex) { LogManager.LogException(ex, string.Format("[GroupManager.GetGroup]Erreur lors de la récupération du groupe '{0}'", groupName)); }
            return group;
        }

        /// <summary>
        /// Crée un groupe d'utilisateurs
        /// </summary>
        /// <param name="groups"></param>
        /// <param name="groupName"></param>
        /// <param name="groupDescription"></param>
        /// <param name="owner"></param>
        /// <returns></returns>
        public static SPGroup CreateGroup(SPGroupCollection groups, string groupName, string groupDescription, SPUser owner)
        {
            SPGroup group = null;
            try
            {
                if (!Security.GroupManager.ContainsGroup(groups, groupName))
                {
                    groups.Add(groupName, owner, owner, groupDescription);
                    group = groups[groupName];

                    LogManager.LogDebug("[GroupManager.CreateGroup] Création du groupe", string.Format("[groupname={0}]", groupName));
                }
                else
                {
                    LogManager.LogDebug("[GroupManager.CreateGroup] Groupe déjà existant", string.Format("[groupname={0}]", groupName));
                    group = GetGroup(groups, groupName);
                }
            }
            catch (Exception ex) { LogManager.LogException(ex, string.Format("[GroupManager.CreateGroup]Erreur lors de la création du groupe '{0}'", groupName)); }
            return group;
        }

        /// <summary>
        /// Assigne un rôle à un groupe pour un objet donné (dont est issu le 'roleAssignments')
        /// </summary>
        /// <param name="group"></param>
        /// <param name="roleAssignments"></param>
        /// <param name="roleDefinition"></param>
        /// <param name="currentWeb"></param>
        public static void AssignRoleToGroupOrUserForObject(SPPrincipal groupOrUser, SPSecurableObject securableObject, string roleDefinition, SPWeb currentWeb, bool logDetail)
        {
            if (groupOrUser != null)
            {
                try
                {
                    SPRoleDefinition role = currentWeb.RoleDefinitions[roleDefinition];
                    if (logDetail) LogManager.LogDebug("[Method.AssignRoleToGroupForObject]", string.Format("role.Name={0}", role.Name));

                    SPRoleAssignment roleAssignment = new SPRoleAssignment(groupOrUser);
                    if (logDetail) LogManager.LogDebug("[Method.AssignRoleToGroupForObject]", string.Format("roleAssignment({0})", groupOrUser));
                    roleAssignment.RoleDefinitionBindings.Add(role);
                    if (logDetail) LogManager.LogDebug("[Method.AssignRoleToGroupForObject]", string.Format("RoleDefinitionBindings.Add(role={0})", roleDefinition));

                    securableObject.RoleAssignments.Add(roleAssignment);

                    LogManager.LogDebug(string.Format("[Method.AssignRoleToGroupForObject][group.Name={0}, roleDefinition={1}]", groupOrUser.Name, roleDefinition), "Assignation des droits effectuée.");
                }
                catch (Exception ex) { LogManager.LogException(ex, "[Method.AssignRoleToGroupForObject] Erreur lors de l'assignation des droits."); }
            }
            else
                LogManager.LogDebug("[Method.AssignRoleToGroupForObject]", "group NULL");

        }
        public static void AssignRoleToGroupOrUserForObject(SPPrincipal groupOrUser, SPSecurableObject securableObject, string roleDefinition, SPWeb currentWeb)
        {
            AssignRoleToGroupOrUserForObject(groupOrUser, securableObject, roleDefinition, currentWeb, true);
        }

        /// <summary>
        /// Ajoute les users au groupe donné
        /// </summary>
        /// <param name="group"></param>
        /// <param name="users"></param>
        public static void AddUsersToGroup(SPGroup group, List<SPUser> users)
        {
            if (group != null && users != null)
                foreach (SPUser user in users)
                {
                    if (!GroupContainsUser(group, user))
                    {
                        try
                        {
                            group.AddUser(user);
                            LogManager.LogDebug("[Method.AddUsersToGroup]", string.Format("Group({0}).AddUser(Login={1})", group.Name, user.LoginName));
                        }
                        catch (Exception ex) { LogManager.LogException(ex, string.Format("[Method.AddUsersToGroup] Erreur lors de l'assignation des droits: Group({0}).AddUser(Login={1}).", group.Name, user.LoginName)); }
                    }
                    else
                        LogManager.LogDebug("[Method.AddUsersToGroup]", string.Format("Group({0}) contains allready the User(Login={1})", group.Name, user.LoginName));
                }
        }

        /// <summary>
        /// Indique si l'utilisateur donné appartient au groupe
        /// </summary>
        /// <param name="group"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public static bool GroupContainsUser(SPGroup group, SPUser user)
        {
            bool contains = false;
            SPUser userGroup = null;
            if (group != null && user != null && group.Users!=null && group.Users.Count > 0)
            {
                try { userGroup = group.Users.GetByID(user.ID); }
                catch {}
                contains = userGroup != null;
            }
            return contains;
        }

        /// <summary>
        /// Retire tous les users du groupe
        /// </summary>
        /// <param name="group"></param>
        public static void ClearUsers(SPGroup group)
        {
            if (group != null)
                foreach (SPUser user in group.Users)
                {
                    try
                    {
                        group.RemoveUser(user);
                        LogManager.LogDebug("[Method.ClearUsers]", string.Format("Group({0}).RemoveUser(Login={1})", group.Name, user.LoginName));
                    }
                    catch (Exception ex) { LogManager.LogException(ex, "[Method.ClearUsers] Erreur lors du retrait du user du groupe."); }
                }
        }
        /// <summary>
        /// Retire les users données du groupe
        /// </summary>
        /// <param name="group"></param>
        /// <param name="users"></param>
        public static void RemoveUsers(SPGroup group, List<SPUser> users)
        {
            if (group != null && users != null)
                foreach (SPUser user in users)
                {
                    try
                    {
                        group.RemoveUser(user);
                        LogManager.LogDebug("[Method.RemoveUsers]", string.Format("Group({0}).RemoveUser(Login={1})", group.Name, user.LoginName));
                    }
                    catch (Exception ex) { LogManager.LogException(ex, "[Method.RemoveUsers] Erreur lors du retrait du user du groupe."); }
                }
        }

    }
}
